Carbon


ControlDefProcPtr

Header: Controls.h Carbon status: Supported

If you wish to define new, nonstandard controls for your application, you must write a control definition function and store it in a resource file as a resource of type 'CDEF'.

typedef SInt32(* ControlDefProcPtr) (
    SInt16 varCode, 
    ControlRef theControl, 
    ControlDefProcMessage message, 
    SInt32 param
);

You would declare your function like this if you were to name it MyControlDefCallback:

SInt32 MyControlDefCallback (
    SInt16 varCode, 
    ControlRef theControl, 
    ControlDefProcMessage message, 
    SInt32 param
);
varCode

The control’s variation code.

theControl

A handle to the control that the operation will affect.

message

A code for the task to be performed. See “Control Definition Message Constants” for a description of the constants which you can use here. The subsections that follow explain each of these tasks in detail.

param

Data associated with the task specified by the message parameter. If the task requires no data, this parameter is ignored.

function result

The function results that your control definition function returns depend on the value that the Control Manager passes in the message parameter.0

DISCUSSION

The Control Manager defines the data type ControlDefUPP to identify the universal procedure pointer for this application-defined function:

typedef UniversalProcPtr ControlDefUPP;

You typically use the NewControlDefProc macro like this:

ControlDefUPP myControlDefUPP;

myControlDefUPP = NewControlDefProc (MyControlDefCallback);

You typically use the CallControlDefProc macro like this:

CallControlDefProc(myControlDefUPP, varCode, theControl, message, param);

A control definition function determines how a control generally looks and behaves. Various Control Manager functions call a control definition function whenever they need to perform a control-dependent action, such as drawing the control on the screen. In addition to standard control definition functions, defined by the system, you can make your own custom control definition functions.

When various Control Manager functions need to perform a type-dependent action on the control, they call the control definition function and pass it the variation code for its type as a parameter. You can define your own variation codes; this allows you to use one 'CDEF' resource to handle several variations of the same general control. See 'CDEF' for further discussion of controls, their resources, and their IDs.

To define your own type of control, you write a control definition function, compile it as a resource of type 'CDEF', and store it in your resource file. Whenever you create a control, you specify a control definition ID, which the Control Manager uses to determine the control definition function. The control definition ID is an integer that contains the resource ID of the control definition function in its upper 12 bits and a variation code in its lower 4 bits. Thus, for a given resource ID and variation code

control definition ID = (16 x resource ID) + variation code

For example, buttons, checkboxes, and radio buttons all use the standard control definition function with resource ID 0. Because they have variation codes of 0, 1, and 2, respectively, their respective control definition IDs are 0, 1, and 2. See the control definition IDs in the “Control Manager Constants” section for more details.

The Control Manager calls the Resource Manager to access a control definition function with the given resource ID. The Resource Manager reads a control definition function into memory and returns a handle to it. The Control Manager stores this handle in the contrlDefProc field of the control structure.

The Control Manager calls your control definition function under various circumstances; the Control Manager uses the message parameter to inform your control definition function what action it must perform. The data that the Control Manager passes in the param parameter, the action that your control definition function must undertake, and the function results that your control definition function returns all depend on the value that the Control Manager passes in the message parameter. The rest of this section describes how to respond to the various values that the Control Manager passes in the message parameter.

Drawing the Control or Its Part

When the Control Manager passes the value drawCntl in the message parameter, your control definition function should respond by drawing the indicator or the entire control.

The Control Manager passes one of the drawing constants described in “Drawing Constants” in the low word of the param parameter to specify whether the user is drawing an indicator or the whole control. The high-order word of the param parameter may contain undefined data; therefore, evaluate only the low-order word of this parameter.

With the exception of part code 128, which is reserved for future use and should not be used, any other value indicates a part code for the control.

If the specified control is visible, your control definition function should draw the control (or the part specified in the param parameter) within the control’s rectangle. If the control is invisible (that is, if its contrlVis field is set to 0), your control definition function does nothing.

When drawing the control or its part, take into account the current values of its contrlHilite and contrlValue fields in the control structure.

If the part code for your control’s indicator is passed in param, assume that the indicator hasn’t moved; the Control Manager, for example, may be calling your control definition function so that you may simply highlight the indicator. However, when your application calls SetControlValue, SetControlMinimum, and SetControlMaximum, they in turn may call your control definition function with the drawCntl message to redraw the indicator. Since these functions have no way of determining what part code you chose for your indicator, they all pass 129 in param, meaning that you should move your indicator. Your control definition function must detect this part code as a special case and remove the indicator from its former location before drawing it. If your control has more than one indicator, you should interpret 129 to mean all indicators.

When sent the message drawCntl, your control definition function should return 0 as its function result.

Testing Where the Mouse-Down Event Occurs

When the Control Manager passes the value for the testCntl constant in the message parameter, your control definition function should respond by determining whether a specified point is in a visible control.

The Control Manager passes a point (in local coordinates) in the param parameter. The point’s vertical coordinate is contained in the high-order word of the long integer, and horizontal coordinate is contained in the low-order word.

Your control definition function should return the part code of the part that contains the specified point; it should return 0 if the point is outside the control or if the control is inactive.

Calculating the Control and Indicator Regions on 24-Bit Systems

When the Control Manager passes the value for the calcCRgns constant in the message parameter, your control definition function should calculate the region passed in the param parameter for the specified control or its indicator.

The Control Manager passes a QuickDraw region handle in the param parameter. If the high-order bit of param is set, the region requested is that of the control’s indicator; otherwise, the region requested is that of the entire control. Your control definition function should clear the high bit of the region handle before calculating the region.

When passed this message, your control definition function should always return 0, and it should express the region in the local coordinate system of the control’s window.

Note that the calcCRgns message will never be sent to any system running on 32-bit mode and is therefore obsolete in Mac OS 7.6 and later. On Mac OS 7.6 and later, the calcCntlRgn and calcThumbRgn messages are sent instead.

Calculating the Control and Indicator Regions on 32-Bit Systems

When the Control Manager passes the values for the calcCntlRgn or calcThumbRgn constants in the message parameter, your control definition function should calculate the region for the specified control or its indicator using the QuickDraw region handle passed in the param parameter .

If the Control Manager passes the value for the calcThumbRgn constant in the message parameter, calculate the region occupied by the indicator. If the Control Manager passes the value for the calcCntlRgn constant in the message parameter, calculate the region for the entire control.

When passed this message, your control definition function should always return 0, and it should express the region in the local coordinate system of the control’s window.

Performing Additional Control Initialization

After initializing fields of a control structure as appropriate when creating a new control, the Control Manager passes initCntl in the message parameter to give your control definition function the opportunity to perform any type-specific initialization you may require. For example, the standard control definition function for scroll bars allocates space for a region to hold the scroll box and stores the region handle in the contrlData field of the new control structure.

When passed the value for the initCntl constant in the message parameter, your control definition function should ignore the param parameter and return 0 as a function result.

Performing Additional Control Disposal Actions

The function DisposeControl passes dispCntl in the message parameter to give your control definition function the opportunity to carry out any additional actions when disposing of a control. For example, the standard definition function for scroll bars releases the memory occupied by the scroll box region, whose handle is kept in the contrlData field of the control structure.

When passed the value for the dispCntl constant in the message parameter, your control definition function should ignore the param parameter and return 0 as a function result.

Dragging the Control or Its Indicator

When a mouse-up event occurs in the indicator of a control, the HandleControlClick or TrackControl functions call your control definition function and pass posCntl in the message parameter. In this case, the Control Manager passes a point (in coordinates local to the control’s window) in the param parameter that specifies the vertical and horizontal offset, in pixels, by which your control definition function should move the indicator from its current position. Typically, this is the offset between the points where the cursor was when the user pressed and released the mouse button while dragging the indicator. The point’s vertical offset is contained in the high-order word of the param parameter, and its horizontal offset is contained in the low-order word.

Your definition function should calculate the control’s new setting based on the given offset and then, to reflect the new setting, redraw the control and update the contrlValue field in the control structure. Your control definition function should ignore the param parameter and return 0 as a function result.

Calculating Parameters for Dragging the Indicator

When the Control Manager passes the value for thumbCntl in the message parameter, your control definition function should respond by calculating values analogous to the limitRect, slopRect, and axis parameters of DragControl that constrain how the indicator is dragged. On entry, the fields param->limitRect.top and param->limitRect.left contain the point where the mouse-down event first occurred.

The Control Manager passes a pointer to a structure of type IndicatorDragConstraint in the param parameter. Your definition function should store the appropriate values into the fields of the structure pointed to by the param parameter; they’re analogous to the similarly named parameters of the Window Manager function DragGrayRgn.

Your control definition function should return 0 as function result.

Performing Custom Dragging

When the Control Manager passes the value for the dragCntl constant in the message parameter, the param parameter typically contains a custom dragging constant with one of the values described in

  • “Drag Control Constants” to specify whether the user is dragging an indicator or the whole control.

    When the Appearance Manager is present, the message kControlMsgHandleTracking should be sent instead of dragCntl to handle any custom tracking; see “Performing Custom Tracking” below.

    If you want to use the Control Manager’s default method of dragging, which is to call DragControl to drag the control or the Window Manager function DragGrayRgn to drag its indicator, return 0 as the function result for your control definition function.

    If your control definition function returns a nonzero value, your control definition function (not the Control Manager) must drag the specified control (or its indicator) to follow the cursor until the user releases the mouse button. If the user drags the entire control, your definition function should use the function MoveControl to reposition the control to its new location after the user releases the mouse button. If the user drags the indicator, your definition function must calculate the control’s new setting (based on the pixel offset between the points where the cursor was when the user pressed and released the mouse button while dragging the indicator) and then, to reflect the new setting, redraw the control and update the contrlValue field in the control structure. Note that, in this case, the functions HandleControlClick and TrackControl return 0 whether or not the user changes the indicator’s position. Thus, you must determine whether the user has changed the control’s setting by another method, for instance, by comparing the control’s value before and after the call to HandleControlClick.

    Executing an Action Function

    The only way to specify actions in response to all mouse-down events in a control or its indicator is to define your own control definition function that specifies an action function. When you create the control, your control definition function must first respond to the initCntl message by storing (ControlDefUPP)-1L in the contrlAction field of the control structure. (The Control Manager sends the initCntl message to your control definition function after initializing the fields of a new control structure.) Then, when your application passes (ControlActionUPP)-1L in the actionProc parameter of HandleControlClick or TrackControl, HandleControlClick calls your control definition function with the autoTrack message. The Control Manager passes the part code of the part where the mouse-down event occurs in the param parameter. Your control definition function should then use this information to respond as an action function would.

    Note that for the autoTrack message, the high-order word of the param parameter may contain undefined data; therefore, evaluate only the low-order word of this parameter.

    If the mouse-down event occurs in an indicator of a control that supports live feedback, your action function should take two parameters (a handle to the control and the part code of the control where the mouse-down event first occurred). This action function is the same one you would use to define actions to be performed in control part codes in response to a mouse-down event; see ControlActionProcPtr.

    If the mouse-down event occurs in an indicator of a control that does not support live feedback, your action function should take no parameters, because the user may move the cursor outside the indicator while dragging it.

    Specifying Whether Appearance-Compliant Messages Are Supported

    If your control definition function supports Appearance-compliant messages, it should return kControlSupportsNewMessages as a function result when the Control Manager passes kControlMsgTestNewMsgSupport in the message parameter.

    Specifying Which Appearance-Compliant Messages Are Supported

    AVAILABILITY

    Supported in Carbon.


    © 2000 Apple Computer, Inc. — (Last Updated 5/8/2000)